package com.gitee.btssplib

import android.util.Log
import com.gitee.btssplib.parser.DefaultDataParser
import io.reactivex.BackpressureStrategy
import io.reactivex.Flowable
import io.reactivex.FlowableOnSubscribe
import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.disposables.Disposable
import io.reactivex.schedulers.Schedulers

/**
 * 蓝牙接收器，负责读取数据.
 * @author John
 * @version 1.0
 */
class BTReceiver(private val connector: BTConnector, private val innerReadDataListener: ReceiveListener) {

    companion object {
        const val TAG = "BTReceiver"
    }

    enum class State {
        IDLE, // 空闲
        RECEIVEING, // 正在接收数据
        RECEIVE_ERROR // 接收数据错误
    }

    private var receiveThread: Disposable? = null // 接收数据线程
    var state: State = State.IDLE // 接收数据状态
    var dataParser: IDataParser<*> = DefaultDataParser()

    @Synchronized
    fun receiveData() {
        when (state) {
            State.IDLE -> {
                receiveBluetoothDeviceData()
            }
            else -> {
                stop()
                receiveBluetoothDeviceData()
            }
        }
    }

    @Synchronized
    fun stop() {
        if (receiveThread != null) {
            Log.d(TAG, "正在停止接收器")
            try {
                receiveThread?.dispose()
            } catch (e: Exception) {
                e.printStackTrace()
            } finally {
                receiveThread = null
                state = State.IDLE
            }
        }
    }

    private fun receiveBluetoothDeviceData() {
        receiveThread = Flowable.create(FlowableOnSubscribe<Any> { emitter ->
            try {
                while (!emitter.isCancelled) {
                    var data: Int? = null
                    var tryCount = 0
                    while (!emitter.isCancelled && data == null) {
                        try {
                            tryCount++
                            data = connector.bluetoothSocket?.inputStream?.read()
                        } catch (e: Exception) {
                            e.printStackTrace()
                            Log.d(TAG, "读数据发生异常，清空数据分析器的缓存")
                            dataParser?.clearCache()
                            if (tryCount <= 3) {
                                Log.d(TAG, "尝试读数据不到3次，5秒后重试")
                                Thread.sleep(5000)
                            } else {
                                Log.d(TAG, "尝试读数据达到3次，判断为断开连接，将异常抛出")
                                throw e
                            }
                        }
                    }
                    if (data != null && data != -1) {
                        dataParser?.parse(data)?.let { result ->
                            emitter.onNext(result)
                        }
                    }
                }
            } catch (e: Exception) {
                e.printStackTrace()
                emitter.tryOnError(e)
            } finally {
                emitter.onComplete()
            }
        }, BackpressureStrategy.LATEST)
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe({ result ->
                    Log.d(TAG, "接收到数据：$result")
                    innerReadDataListener?.onResult(result)
                }, { error ->
                    Log.d(TAG, "接收数据发生错误")
                    state = State.RECEIVE_ERROR
                    error.printStackTrace()
                    innerReadDataListener?.onError(error)
                }, {
                    Log.d(TAG, "接收数据结束")
                }, { subscription ->
                    Log.d(TAG, "开始接收数据")
                    subscription.request(Long.MAX_VALUE)
                    state = State.RECEIVEING
                    innerReadDataListener?.onStart()
                })
    }
}